//----------------------------------------------------------------------------
//  ,-.
// /_\___ ,   Ninja Framework
// '  ___\    (C) Riccardo Capra - http://riccar.do
//  //   \\
//----------------------------------------------------------------------------
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
//----------------------------------------------------------------------------

#ifndef NJ_ATOMIC_H
#	define NJ_ATOMIC_H

#	include "NjNinjaSyncLib.h"
#	include "NjAtomicBase.h"

	/// \brief Collects atomic operations on type \em tType
	/// \param tType the type on which operate atomically
	template <class tType>
	class NjAtomic : public NjAtomicBase<sizeof(tType)>
	{
	public:
		/// \brief The type used in this class implementation
		typedef tType Type;

		/// \copydoc NjAtomicBase<4>::NjAtomicBase()
		NjAtomic();

		/// \copydoc NjAtomicBase<4>::NjAtomicBase(NjAtomicBase const &)
		NjAtomic(NjAtomic const & kCopy);

		/// \copydoc NjAtomicBase<4>::NjAtomicBase(Number)
		NjAtomic(Type iCopy);

		/// \copydoc NjAtomicBase<4>::~NjAtomicBase
		~NjAtomic();

		/// \copydoc NjAtomicBase<4>::Increment
		void Increment();

		/// \copydoc NjAtomicBase<4>::PreIncrement
		Type PreIncrement();

		/// \copydoc NjAtomicBase<4>::PostIncrement
		Type PostIncrement();

		/// \copydoc NjAtomicBase<4>::Decrement
		void Decrement();

		/// \copydoc NjAtomicBase<4>::PreDecrement
		Type PreDecrement();

		/// \copydoc NjAtomicBase<4>::PostDecrement
		Type PostDecrement();

		/// \copydoc NjAtomicBase<4>::Add
		void Add(Type iRightValue);

		/// \copydoc NjAtomicBase<4>::PreAdd
		Type PreAdd(Type iRightValue);

		/// \copydoc NjAtomicBase<4>::PostAdd
		Type PostAdd(Type iRightValue);

		/// \copydoc NjAtomicBase<4>::Sub
		void Sub(Type iRightValue);

		/// \copydoc NjAtomicBase<4>::PreSub
		Type PreSub(Type iRightValue);

		/// \copydoc NjAtomicBase<4>::PostSub
		Type PostSub(Type iRightValue);

		/// \copydoc NjAtomicBase<4>::PostOr
		Type PostOr(Type iRightValue);

		/// \copydoc NjAtomicBase<4>::PostAnd
		Type PostAnd(Type iRightValue);

		/// \copydoc NjAtomicBase<4>::PostXor
		Type PostXor(Type iRightValue);

		/// \copydoc NjAtomicBase<4>::PostExchange
		Type PostExchange(Type iValue);

		/// \copydoc NjAtomicBase<4>::PostCompareExchange
		Type PostCompareExchange(Type iComparand, Type iValue);

		/// \copydoc NjAtomicBase<4>::PostSetBit
		NjBool PostSetBit(Type iBit);

		/// \copydoc NjAtomicBase<4>::PostResetBit
		NjBool PostResetBit(Type iBit);

		/// \copydoc NjAtomicBase<4>::Get
		Type Get() const;

		/// \copydoc NjAtomicBase<4>::Set
		void Set(Type iValue);

	private:
		/// \brief The underlying parent class
		typedef NjAtomicBase<sizeof(tType)> Parent;

		NJ_DISABLE_ASSIGNMENT_OPERATOR(NjAtomic);
	};

	/// \brief Collects atomic operations on pointers of type \em tType
	/// \param tType the type on whose pointer operate atomically
	template <class tType>
	class NjAtomic<tType *> : public NjAtomicBase<sizeof(tType *)>
	{
	public:
		/// \brief The type used in this class implementation
		typedef tType * Type;

		/// \copydoc NjAtomicBase<4>::NjAtomicBase()
		NjAtomic();

		/// \copydoc NjAtomicBase<4>::NjAtomicBase(NjAtomicBase const &)
		NjAtomic(NjAtomic const & kCopy);

		/// \copydoc NjAtomicBase<4>::NjAtomicBase(Number)
		NjAtomic(Type iCopy);

		/// \copydoc NjAtomicBase<4>::~NjAtomicBase
		~NjAtomic();

		/// \copydoc NjAtomicBase<4>::Increment
		void Increment();

		/// \copydoc NjAtomicBase<4>::PreIncrement
		Type PreIncrement();

		/// \copydoc NjAtomicBase<4>::PostIncrement
		Type PostIncrement();

		/// \copydoc NjAtomicBase<4>::Decrement
		void Decrement();

		/// \copydoc NjAtomicBase<4>::PreDecrement
		Type PreDecrement();

		/// \copydoc NjAtomicBase<4>::PostDecrement
		Type PostDecrement();

		/// \copydoc NjAtomicBase<4>::Add
		void Add(NjUint iRightValue);

		/// \copydoc NjAtomicBase<4>::PreAdd
		Type PreAdd(NjUint iRightValue);

		/// \copydoc NjAtomicBase<4>::PostAdd
		Type PostAdd(NjUint iRightValue);

		/// \copydoc NjAtomicBase<4>::Sub
		void Sub(NjUint iRightValue);

		/// \copydoc NjAtomicBase<4>::PreSub
		Type PreSub(NjUint iRightValue);

		/// \copydoc NjAtomicBase<4>::PostSub
		Type PostSub(NjUint iRightValue);

		/// \copydoc NjAtomicBase<4>::PostExchange
		Type PostExchange(Type iValue);

		/// \copydoc NjAtomicBase<4>::PostCompareExchange
		Type PostCompareExchange(Type iComparand, Type iValue);

		/// \copydoc NjAtomicBase<4>::Get
		Type Get() const;

		/// \copydoc NjAtomicBase<4>::Set
		void Set(Type iValue);

	private:
		/// \brief The underlying parent class
		typedef NjAtomicBase<sizeof(tType *)> Parent;

		NJ_DISABLE_ASSIGNMENT_OPERATOR(NjAtomic);
	};

#	include "NjAtomic_inline.h"

#endif // NJ_ATOMIC_H
